home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / xmlrpclib.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-11-11  |  41KB  |  1,278 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. An XML-RPC client interface for Python.
  6.  
  7. The marshalling and response parser code can also be used to
  8. implement XML-RPC servers.
  9.  
  10. Exported exceptions:
  11.  
  12.   Error          Base class for client errors
  13.   ProtocolError  Indicates an HTTP protocol error
  14.   ResponseError  Indicates a broken response package
  15.   Fault          Indicates an XML-RPC fault package
  16.  
  17. Exported classes:
  18.  
  19.   ServerProxy    Represents a logical connection to an XML-RPC server
  20.  
  21.   MultiCall      Executor of boxcared xmlrpc requests
  22.   Boolean        boolean wrapper to generate a "boolean" XML-RPC value
  23.   DateTime       dateTime wrapper for an ISO 8601 string or time tuple or
  24.                  localtime integer value to generate a "dateTime.iso8601"
  25.                  XML-RPC value
  26.   Binary         binary data wrapper
  27.  
  28.   SlowParser     Slow but safe standard parser (based on xmllib)
  29.   Marshaller     Generate an XML-RPC params chunk from a Python data structure
  30.   Unmarshaller   Unmarshal an XML-RPC response from incoming XML event message
  31.   Transport      Handles an HTTP transaction to an XML-RPC server
  32.   SafeTransport  Handles an HTTPS transaction to an XML-RPC server
  33.  
  34. Exported constants:
  35.  
  36.   True
  37.   False
  38.  
  39. Exported functions:
  40.  
  41.   boolean        Convert any Python value to an XML-RPC boolean
  42.   getparser      Create instance of the fastest available parser & attach
  43.                  to an unmarshalling object
  44.   dumps          Convert an argument tuple or a Fault instance to an XML-RPC
  45.                  request (or response, if the methodresponse option is used).
  46.   loads          Convert an XML-RPC packet to unmarshalled data plus a method
  47.                  name (None if not present).
  48. '''
  49. import re
  50. import string
  51. import time
  52. import operator
  53. from types import *
  54.  
  55. try:
  56.     unicode
  57. except NameError:
  58.     unicode = None
  59.  
  60.  
  61. try:
  62.     import datetime
  63. except ImportError:
  64.     datetime = None
  65.  
  66.  
  67. try:
  68.     _bool_is_builtin = False.__class__.__name__ == 'bool'
  69. except NameError:
  70.     _bool_is_builtin = 0
  71.  
  72.  
  73. def _decode(data, encoding, is8bit = re.compile('[\x80-\xff]').search):
  74.     if unicode and encoding and is8bit(data):
  75.         data = unicode(data, encoding)
  76.     
  77.     return data
  78.  
  79.  
  80. def escape(s, replace = string.replace):
  81.     s = replace(s, '&', '&')
  82.     s = replace(s, '<', '<')
  83.     return replace(s, '>', '>')
  84.  
  85. if unicode:
  86.     
  87.     def _stringify(string):
  88.         
  89.         try:
  90.             return string.encode('ascii')
  91.         except UnicodeError:
  92.             return string
  93.  
  94.  
  95. else:
  96.     
  97.     def _stringify(string):
  98.         return string
  99.  
  100. __version__ = '1.0.1'
  101. MAXINT = 0x7FFFFFFFL
  102. MININT = -0x80000000L
  103. PARSE_ERROR = -32700
  104. SERVER_ERROR = -32600
  105. APPLICATION_ERROR = -32500
  106. SYSTEM_ERROR = -32400
  107. TRANSPORT_ERROR = -32300
  108. NOT_WELLFORMED_ERROR = -32700
  109. UNSUPPORTED_ENCODING = -32701
  110. INVALID_ENCODING_CHAR = -32702
  111. INVALID_XMLRPC = -32600
  112. METHOD_NOT_FOUND = -32601
  113. INVALID_METHOD_PARAMS = -32602
  114. INTERNAL_ERROR = -32603
  115.  
  116. class Error(Exception):
  117.     '''Base class for client errors.'''
  118.     
  119.     def __str__(self):
  120.         return repr(self)
  121.  
  122.  
  123.  
  124. class ProtocolError(Error):
  125.     '''Indicates an HTTP protocol error.'''
  126.     
  127.     def __init__(self, url, errcode, errmsg, headers):
  128.         Error.__init__(self)
  129.         self.url = url
  130.         self.errcode = errcode
  131.         self.errmsg = errmsg
  132.         self.headers = headers
  133.  
  134.     
  135.     def __repr__(self):
  136.         return '<ProtocolError for %s: %s %s>' % (self.url, self.errcode, self.errmsg)
  137.  
  138.  
  139.  
  140. class ResponseError(Error):
  141.     '''Indicates a broken response package.'''
  142.     pass
  143.  
  144.  
  145. class Fault(Error):
  146.     '''Indicates an XML-RPC fault package.'''
  147.     
  148.     def __init__(self, faultCode, faultString, **extra):
  149.         Error.__init__(self)
  150.         self.faultCode = faultCode
  151.         self.faultString = faultString
  152.  
  153.     
  154.     def __repr__(self):
  155.         return '<Fault %s: %s>' % (self.faultCode, repr(self.faultString))
  156.  
  157.  
  158. from sys import modules
  159. mod_dict = modules[__name__].__dict__
  160. if _bool_is_builtin:
  161.     boolean = Boolean = bool
  162.     mod_dict['True'] = True
  163.     mod_dict['False'] = False
  164. else:
  165.     
  166.     class Boolean:
  167.         '''Boolean-value wrapper.
  168.  
  169.         Use True or False to generate a "boolean" XML-RPC value.
  170.         '''
  171.         
  172.         def __init__(self, value = 0):
  173.             self.value = operator.truth(value)
  174.  
  175.         
  176.         def encode(self, out):
  177.             out.write('<value><boolean>%d</boolean></value>\n' % self.value)
  178.  
  179.         
  180.         def __cmp__(self, other):
  181.             if isinstance(other, Boolean):
  182.                 other = other.value
  183.             
  184.             return cmp(self.value, other)
  185.  
  186.         
  187.         def __repr__(self):
  188.             if self.value:
  189.                 return '<Boolean True at %x>' % id(self)
  190.             return '<Boolean False at %x>' % id(self)
  191.  
  192.         
  193.         def __int__(self):
  194.             return self.value
  195.  
  196.         
  197.         def __nonzero__(self):
  198.             return self.value
  199.  
  200.  
  201.     mod_dict['True'] = Boolean(1)
  202.     mod_dict['False'] = Boolean(0)
  203.     
  204.     def boolean(value, _truefalse = (False, True)):
  205.         """Convert any Python value to XML-RPC 'boolean'."""
  206.         return _truefalse[operator.truth(value)]
  207.  
  208. del modules
  209. del mod_dict
  210.  
  211. def _strftime(value):
  212.     if datetime:
  213.         if isinstance(value, datetime.datetime):
  214.             return '%04d%02d%02dT%02d:%02d:%02d' % (value.year, value.month, value.day, value.hour, value.minute, value.second)
  215.     
  216.     if not isinstance(value, (TupleType, time.struct_time)):
  217.         if value == 0:
  218.             value = time.time()
  219.         
  220.         value = time.localtime(value)
  221.     
  222.     return '%04d%02d%02dT%02d:%02d:%02d' % value[:6]
  223.  
  224.  
  225. class DateTime:
  226.     """DateTime wrapper for an ISO 8601 string or time tuple or
  227.     localtime integer value to generate 'dateTime.iso8601' XML-RPC
  228.     value.
  229.     """
  230.     
  231.     def __init__(self, value = 0):
  232.         if isinstance(value, StringType):
  233.             self.value = value
  234.         else:
  235.             self.value = _strftime(value)
  236.  
  237.     
  238.     def make_comparable(self, other):
  239.         if isinstance(other, DateTime):
  240.             s = self.value
  241.             o = other.value
  242.         elif datetime and isinstance(other, datetime.datetime):
  243.             s = self.value
  244.             o = other.strftime('%Y%m%dT%H:%M:%S')
  245.         elif isinstance(other, (str, unicode)):
  246.             s = self.value
  247.             o = other
  248.         elif hasattr(other, 'timetuple'):
  249.             s = self.timetuple()
  250.             o = other.timetuple()
  251.         elif not hasattr(other, '__class__') or other.__class__.__name__:
  252.             pass
  253.         otype = type(other)
  254.         raise TypeError("Can't compare %s and %s" % (self.__class__.__name__, otype))
  255.         return (s, o)
  256.  
  257.     
  258.     def __lt__(self, other):
  259.         (s, o) = self.make_comparable(other)
  260.         return s < o
  261.  
  262.     
  263.     def __le__(self, other):
  264.         (s, o) = self.make_comparable(other)
  265.         return s <= o
  266.  
  267.     
  268.     def __gt__(self, other):
  269.         (s, o) = self.make_comparable(other)
  270.         return s > o
  271.  
  272.     
  273.     def __ge__(self, other):
  274.         (s, o) = self.make_comparable(other)
  275.         return s >= o
  276.  
  277.     
  278.     def __eq__(self, other):
  279.         (s, o) = self.make_comparable(other)
  280.         return s == o
  281.  
  282.     
  283.     def __ne__(self, other):
  284.         (s, o) = self.make_comparable(other)
  285.         return s != o
  286.  
  287.     
  288.     def timetuple(self):
  289.         return time.strptime(self.value, '%Y%m%dT%H:%M:%S')
  290.  
  291.     
  292.     def __cmp__(self, other):
  293.         (s, o) = self.make_comparable(other)
  294.         return cmp(s, o)
  295.  
  296.     
  297.     def __str__(self):
  298.         return self.value
  299.  
  300.     
  301.     def __repr__(self):
  302.         return '<DateTime %s at %x>' % (repr(self.value), id(self))
  303.  
  304.     
  305.     def decode(self, data):
  306.         data = str(data)
  307.         self.value = string.strip(data)
  308.  
  309.     
  310.     def encode(self, out):
  311.         out.write('<value><dateTime.iso8601>')
  312.         out.write(self.value)
  313.         out.write('</dateTime.iso8601></value>\n')
  314.  
  315.  
  316.  
  317. def _datetime(data):
  318.     value = DateTime()
  319.     value.decode(data)
  320.     return value
  321.  
  322.  
  323. def _datetime_type(data):
  324.     t = time.strptime(data, '%Y%m%dT%H:%M:%S')
  325.     return datetime.datetime(*tuple(t)[:6])
  326.  
  327. import base64
  328.  
  329. try:
  330.     import cStringIO as StringIO
  331. except ImportError:
  332.     import StringIO
  333.  
  334.  
  335. class Binary:
  336.     '''Wrapper for binary data.'''
  337.     
  338.     def __init__(self, data = None):
  339.         self.data = data
  340.  
  341.     
  342.     def __str__(self):
  343.         if not self.data:
  344.             pass
  345.         return ''
  346.  
  347.     
  348.     def __cmp__(self, other):
  349.         if isinstance(other, Binary):
  350.             other = other.data
  351.         
  352.         return cmp(self.data, other)
  353.  
  354.     
  355.     def decode(self, data):
  356.         self.data = base64.decodestring(data)
  357.  
  358.     
  359.     def encode(self, out):
  360.         out.write('<value><base64>\n')
  361.         base64.encode(StringIO.StringIO(self.data), out)
  362.         out.write('</base64></value>\n')
  363.  
  364.  
  365.  
  366. def _binary(data):
  367.     value = Binary()
  368.     value.decode(data)
  369.     return value
  370.  
  371. WRAPPERS = (DateTime, Binary)
  372. if not _bool_is_builtin:
  373.     WRAPPERS = WRAPPERS + (Boolean,)
  374.  
  375.  
  376. try:
  377.     import _xmlrpclib
  378.     FastParser = _xmlrpclib.Parser
  379.     FastUnmarshaller = _xmlrpclib.Unmarshaller
  380. except (AttributeError, ImportError):
  381.     FastParser = None
  382.     FastUnmarshaller = None
  383.  
  384.  
  385. try:
  386.     import _xmlrpclib
  387.     FastMarshaller = _xmlrpclib.Marshaller
  388. except (AttributeError, ImportError):
  389.     FastMarshaller = None
  390.  
  391.  
  392. try:
  393.     import sgmlop
  394.     if not hasattr(sgmlop, 'XMLParser'):
  395.         raise ImportError
  396.     hasattr(sgmlop, 'XMLParser')
  397. except ImportError:
  398.     SgmlopParser = None
  399.  
  400.  
  401. class SgmlopParser:
  402.     
  403.     def __init__(self, target):
  404.         self.finish_starttag = target.start
  405.         self.finish_endtag = target.end
  406.         self.handle_data = target.data
  407.         self.handle_xml = target.xml
  408.         self.parser = sgmlop.XMLParser()
  409.         self.parser.register(self)
  410.         self.feed = self.parser.feed
  411.         self.entity = {
  412.             'amp': '&',
  413.             'gt': '>',
  414.             'lt': '<',
  415.             'apos': "'",
  416.             'quot': '"' }
  417.  
  418.     
  419.     def close(self):
  420.         
  421.         try:
  422.             self.parser.close()
  423.         finally:
  424.             self.parser = None
  425.             self.feed = None
  426.  
  427.  
  428.     
  429.     def handle_proc(self, tag, attr):
  430.         m = re.search('encoding\\s*=\\s*[\'"]([^"\']+)["\']', attr)
  431.         if m:
  432.             self.handle_xml(m.group(1), 1)
  433.         
  434.  
  435.     
  436.     def handle_entityref(self, entity):
  437.         
  438.         try:
  439.             self.handle_data(self.entity[entity])
  440.         except KeyError:
  441.             self.handle_data('&%s;' % entity)
  442.  
  443.  
  444.  
  445.  
  446. try:
  447.     from xml.parsers import expat
  448.     if not hasattr(expat, 'ParserCreate'):
  449.         raise ImportError
  450.     hasattr(expat, 'ParserCreate')
  451. except ImportError:
  452.     ExpatParser = None
  453.  
  454.  
  455. class ExpatParser:
  456.     
  457.     def __init__(self, target):
  458.         self._parser = parser = expat.ParserCreate(None, None)
  459.         self._target = target
  460.         parser.StartElementHandler = target.start
  461.         parser.EndElementHandler = target.end
  462.         parser.CharacterDataHandler = target.data
  463.         encoding = None
  464.         if not parser.returns_unicode:
  465.             encoding = 'utf-8'
  466.         
  467.         target.xml(encoding, None)
  468.  
  469.     
  470.     def feed(self, data):
  471.         self._parser.Parse(data, 0)
  472.  
  473.     
  474.     def close(self):
  475.         self._parser.Parse('', 1)
  476.         del self._target
  477.         del self._parser
  478.  
  479.  
  480.  
  481. class SlowParser:
  482.     '''Default XML parser (based on xmllib.XMLParser).'''
  483.     
  484.     def __init__(self, target):
  485.         import xmllib as xmllib
  486.         if xmllib.XMLParser not in SlowParser.__bases__:
  487.             SlowParser.__bases__ = (xmllib.XMLParser,)
  488.         
  489.         self.handle_xml = target.xml
  490.         self.unknown_starttag = target.start
  491.         self.handle_data = target.data
  492.         self.handle_cdata = target.data
  493.         self.unknown_endtag = target.end
  494.         
  495.         try:
  496.             xmllib.XMLParser.__init__(self, accept_utf8 = 1)
  497.         except TypeError:
  498.             xmllib.XMLParser.__init__(self)
  499.  
  500.  
  501.  
  502.  
  503. class Marshaller:
  504.     '''Generate an XML-RPC params chunk from a Python data structure.
  505.  
  506.     Create a Marshaller instance for each set of parameters, and use
  507.     the "dumps" method to convert your data (represented as a tuple)
  508.     to an XML-RPC params chunk.  To write a fault response, pass a
  509.     Fault instance instead.  You may prefer to use the "dumps" module
  510.     function for this purpose.
  511.     '''
  512.     
  513.     def __init__(self, encoding = None, allow_none = 0):
  514.         self.memo = { }
  515.         self.data = None
  516.         self.encoding = encoding
  517.         self.allow_none = allow_none
  518.  
  519.     dispatch = { }
  520.     
  521.     def dumps(self, values):
  522.         out = []
  523.         write = out.append
  524.         dump = self._Marshaller__dump
  525.         if isinstance(values, Fault):
  526.             write('<fault>\n')
  527.             dump({
  528.                 'faultCode': values.faultCode,
  529.                 'faultString': values.faultString }, write)
  530.             write('</fault>\n')
  531.         else:
  532.             write('<params>\n')
  533.             for v in values:
  534.                 write('<param>\n')
  535.                 dump(v, write)
  536.                 write('</param>\n')
  537.             
  538.             write('</params>\n')
  539.         result = string.join(out, '')
  540.         return result
  541.  
  542.     
  543.     def __dump(self, value, write):
  544.         
  545.         try:
  546.             f = self.dispatch[type(value)]
  547.         except KeyError:
  548.             
  549.             try:
  550.                 value.__dict__
  551.             except:
  552.                 raise TypeError, 'cannot marshal %s objects' % type(value)
  553.  
  554.             for type_ in type(value).__mro__:
  555.                 if type_ in self.dispatch.keys():
  556.                     raise TypeError, 'cannot marshal %s objects' % type(value)
  557.                 type_ in self.dispatch.keys()
  558.             
  559.             f = self.dispatch[InstanceType]
  560.  
  561.         f(self, value, write)
  562.  
  563.     
  564.     def dump_nil(self, value, write):
  565.         if not self.allow_none:
  566.             raise TypeError, 'cannot marshal None unless allow_none is enabled'
  567.         self.allow_none
  568.         write('<value><nil/></value>')
  569.  
  570.     dispatch[NoneType] = dump_nil
  571.     
  572.     def dump_int(self, value, write):
  573.         if value > MAXINT or value < MININT:
  574.             raise OverflowError, 'int exceeds XML-RPC limits'
  575.         value < MININT
  576.         write('<value><int>')
  577.         write(str(value))
  578.         write('</int></value>\n')
  579.  
  580.     dispatch[IntType] = dump_int
  581.     if _bool_is_builtin:
  582.         
  583.         def dump_bool(self, value, write):
  584.             write('<value><boolean>')
  585.             if not value or '1':
  586.                 pass
  587.             write('0')
  588.             write('</boolean></value>\n')
  589.  
  590.         dispatch[bool] = dump_bool
  591.     
  592.     
  593.     def dump_long(self, value, write):
  594.         if value > MAXINT or value < MININT:
  595.             raise OverflowError, 'long int exceeds XML-RPC limits'
  596.         value < MININT
  597.         write('<value><int>')
  598.         write(str(int(value)))
  599.         write('</int></value>\n')
  600.  
  601.     dispatch[LongType] = dump_long
  602.     
  603.     def dump_double(self, value, write):
  604.         write('<value><double>')
  605.         write(repr(value))
  606.         write('</double></value>\n')
  607.  
  608.     dispatch[FloatType] = dump_double
  609.     
  610.     def dump_string(self, value, write, escape = escape):
  611.         write('<value><string>')
  612.         write(escape(value))
  613.         write('</string></value>\n')
  614.  
  615.     dispatch[StringType] = dump_string
  616.     if unicode:
  617.         
  618.         def dump_unicode(self, value, write, escape = escape):
  619.             value = value.encode(self.encoding)
  620.             write('<value><string>')
  621.             write(escape(value))
  622.             write('</string></value>\n')
  623.  
  624.         dispatch[UnicodeType] = dump_unicode
  625.     
  626.     
  627.     def dump_array(self, value, write):
  628.         i = id(value)
  629.         if i in self.memo:
  630.             raise TypeError, 'cannot marshal recursive sequences'
  631.         i in self.memo
  632.         self.memo[i] = None
  633.         dump = self._Marshaller__dump
  634.         write('<value><array><data>\n')
  635.         for v in value:
  636.             dump(v, write)
  637.         
  638.         write('</data></array></value>\n')
  639.         del self.memo[i]
  640.  
  641.     dispatch[TupleType] = dump_array
  642.     dispatch[ListType] = dump_array
  643.     
  644.     def dump_struct(self, value, write, escape = escape):
  645.         i = id(value)
  646.         if i in self.memo:
  647.             raise TypeError, 'cannot marshal recursive dictionaries'
  648.         i in self.memo
  649.         self.memo[i] = None
  650.         dump = self._Marshaller__dump
  651.         write('<value><struct>\n')
  652.         for k, v in value.items():
  653.             write('<member>\n')
  654.             if type(k) is not StringType:
  655.                 if unicode and type(k) is UnicodeType:
  656.                     k = k.encode(self.encoding)
  657.                 else:
  658.                     raise TypeError, 'dictionary key must be string'
  659.             type(k) is UnicodeType
  660.             write('<name>%s</name>\n' % escape(k))
  661.             dump(v, write)
  662.             write('</member>\n')
  663.         
  664.         write('</struct></value>\n')
  665.         del self.memo[i]
  666.  
  667.     dispatch[DictType] = dump_struct
  668.     if datetime:
  669.         
  670.         def dump_datetime(self, value, write):
  671.             write('<value><dateTime.iso8601>')
  672.             write(_strftime(value))
  673.             write('</dateTime.iso8601></value>\n')
  674.  
  675.         dispatch[datetime.datetime] = dump_datetime
  676.     
  677.     
  678.     def dump_instance(self, value, write):
  679.         if value.__class__ in WRAPPERS:
  680.             self.write = write
  681.             value.encode(self)
  682.             del self.write
  683.         else:
  684.             self.dump_struct(value.__dict__, write)
  685.  
  686.     dispatch[InstanceType] = dump_instance
  687.  
  688.  
  689. class Unmarshaller:
  690.     '''Unmarshal an XML-RPC response, based on incoming XML event
  691.     messages (start, data, end).  Call close() to get the resulting
  692.     data structure.
  693.  
  694.     Note that this reader is fairly tolerant, and gladly accepts bogus
  695.     XML-RPC data without complaining (but not bogus XML).
  696.     '''
  697.     
  698.     def __init__(self, use_datetime = 0):
  699.         self._type = None
  700.         self._stack = []
  701.         self._marks = []
  702.         self._data = []
  703.         self._methodname = None
  704.         self._encoding = 'utf-8'
  705.         self.append = self._stack.append
  706.         self._use_datetime = use_datetime
  707.         if use_datetime and not datetime:
  708.             raise ValueError, 'the datetime module is not available'
  709.         not datetime
  710.  
  711.     
  712.     def close(self):
  713.         if self._type is None or self._marks:
  714.             raise ResponseError()
  715.         self._marks
  716.         if self._type == 'fault':
  717.             raise Fault(**self._stack[0])
  718.         self._type == 'fault'
  719.         return tuple(self._stack)
  720.  
  721.     
  722.     def getmethodname(self):
  723.         return self._methodname
  724.  
  725.     
  726.     def xml(self, encoding, standalone):
  727.         self._encoding = encoding
  728.  
  729.     
  730.     def start(self, tag, attrs):
  731.         if tag == 'array' or tag == 'struct':
  732.             self._marks.append(len(self._stack))
  733.         
  734.         self._data = []
  735.         self._value = tag == 'value'
  736.  
  737.     
  738.     def data(self, text):
  739.         self._data.append(text)
  740.  
  741.     
  742.     def end(self, tag, join = string.join):
  743.         
  744.         try:
  745.             f = self.dispatch[tag]
  746.         except KeyError:
  747.             pass
  748.  
  749.         return f(self, join(self._data, ''))
  750.  
  751.     
  752.     def end_dispatch(self, tag, data):
  753.         
  754.         try:
  755.             f = self.dispatch[tag]
  756.         except KeyError:
  757.             pass
  758.  
  759.         return f(self, data)
  760.  
  761.     dispatch = { }
  762.     
  763.     def end_nil(self, data):
  764.         self.append(None)
  765.         self._value = 0
  766.  
  767.     dispatch['nil'] = end_nil
  768.     
  769.     def end_boolean(self, data):
  770.         if data == '0':
  771.             self.append(False)
  772.         elif data == '1':
  773.             self.append(True)
  774.         else:
  775.             raise TypeError, 'bad boolean value'
  776.         self._value = data == '0'
  777.  
  778.     dispatch['boolean'] = end_boolean
  779.     
  780.     def end_int(self, data):
  781.         self.append(int(data))
  782.         self._value = 0
  783.  
  784.     dispatch['i4'] = end_int
  785.     dispatch['i8'] = end_int
  786.     dispatch['int'] = end_int
  787.     
  788.     def end_double(self, data):
  789.         self.append(float(data))
  790.         self._value = 0
  791.  
  792.     dispatch['double'] = end_double
  793.     
  794.     def end_string(self, data):
  795.         if self._encoding:
  796.             data = _decode(data, self._encoding)
  797.         
  798.         self.append(_stringify(data))
  799.         self._value = 0
  800.  
  801.     dispatch['string'] = end_string
  802.     dispatch['name'] = end_string
  803.     
  804.     def end_array(self, data):
  805.         mark = self._marks.pop()
  806.         self._stack[mark:] = [
  807.             self._stack[mark:]]
  808.         self._value = 0
  809.  
  810.     dispatch['array'] = end_array
  811.     
  812.     def end_struct(self, data):
  813.         mark = self._marks.pop()
  814.         dict = { }
  815.         items = self._stack[mark:]
  816.         for i in range(0, len(items), 2):
  817.             dict[_stringify(items[i])] = items[i + 1]
  818.         
  819.         self._stack[mark:] = [
  820.             dict]
  821.         self._value = 0
  822.  
  823.     dispatch['struct'] = end_struct
  824.     
  825.     def end_base64(self, data):
  826.         value = Binary()
  827.         value.decode(data)
  828.         self.append(value)
  829.         self._value = 0
  830.  
  831.     dispatch['base64'] = end_base64
  832.     
  833.     def end_dateTime(self, data):
  834.         value = DateTime()
  835.         value.decode(data)
  836.         if self._use_datetime:
  837.             value = _datetime_type(data)
  838.         
  839.         self.append(value)
  840.  
  841.     dispatch['dateTime.iso8601'] = end_dateTime
  842.     
  843.     def end_value(self, data):
  844.         if self._value:
  845.             self.end_string(data)
  846.         
  847.  
  848.     dispatch['value'] = end_value
  849.     
  850.     def end_params(self, data):
  851.         self._type = 'params'
  852.  
  853.     dispatch['params'] = end_params
  854.     
  855.     def end_fault(self, data):
  856.         self._type = 'fault'
  857.  
  858.     dispatch['fault'] = end_fault
  859.     
  860.     def end_methodName(self, data):
  861.         if self._encoding:
  862.             data = _decode(data, self._encoding)
  863.         
  864.         self._methodname = data
  865.         self._type = 'methodName'
  866.  
  867.     dispatch['methodName'] = end_methodName
  868.  
  869.  
  870. class _MultiCallMethod:
  871.     
  872.     def __init__(self, call_list, name):
  873.         self._MultiCallMethod__call_list = call_list
  874.         self._MultiCallMethod__name = name
  875.  
  876.     
  877.     def __getattr__(self, name):
  878.         return _MultiCallMethod(self._MultiCallMethod__call_list, '%s.%s' % (self._MultiCallMethod__name, name))
  879.  
  880.     
  881.     def __call__(self, *args):
  882.         self._MultiCallMethod__call_list.append((self._MultiCallMethod__name, args))
  883.  
  884.  
  885.  
  886. class MultiCallIterator:
  887.     '''Iterates over the results of a multicall. Exceptions are
  888.     thrown in response to xmlrpc faults.'''
  889.     
  890.     def __init__(self, results):
  891.         self.results = results
  892.  
  893.     
  894.     def __getitem__(self, i):
  895.         item = self.results[i]
  896.         if type(item) == type({ }):
  897.             raise Fault(item['faultCode'], item['faultString'])
  898.         type(item) == type({ })
  899.         if type(item) == type([]):
  900.             return item[0]
  901.         raise ValueError, 'unexpected type in multicall result'
  902.  
  903.  
  904.  
  905. class MultiCall:
  906.     '''server -> a object used to boxcar method calls
  907.  
  908.     server should be a ServerProxy object.
  909.  
  910.     Methods can be added to the MultiCall using normal
  911.     method call syntax e.g.:
  912.  
  913.     multicall = MultiCall(server_proxy)
  914.     multicall.add(2,3)
  915.     multicall.get_address("Guido")
  916.  
  917.     To execute the multicall, call the MultiCall object e.g.:
  918.  
  919.     add_result, address = multicall()
  920.     '''
  921.     
  922.     def __init__(self, server):
  923.         self._MultiCall__server = server
  924.         self._MultiCall__call_list = []
  925.  
  926.     
  927.     def __repr__(self):
  928.         return '<MultiCall at %x>' % id(self)
  929.  
  930.     __str__ = __repr__
  931.     
  932.     def __getattr__(self, name):
  933.         return _MultiCallMethod(self._MultiCall__call_list, name)
  934.  
  935.     
  936.     def __call__(self):
  937.         marshalled_list = []
  938.         for name, args in self._MultiCall__call_list:
  939.             marshalled_list.append({
  940.                 'methodName': name,
  941.                 'params': args })
  942.         
  943.         return MultiCallIterator(self._MultiCall__server.system.multicall(marshalled_list))
  944.  
  945.  
  946.  
  947. def getparser(use_datetime = 0):
  948.     '''getparser() -> parser, unmarshaller
  949.  
  950.     Create an instance of the fastest available parser, and attach it
  951.     to an unmarshalling object.  Return both objects.
  952.     '''
  953.     if use_datetime and not datetime:
  954.         raise ValueError, 'the datetime module is not available'
  955.     not datetime
  956.     if FastParser and FastUnmarshaller:
  957.         if use_datetime:
  958.             mkdatetime = _datetime_type
  959.         else:
  960.             mkdatetime = _datetime
  961.         target = FastUnmarshaller(True, False, _binary, mkdatetime, Fault)
  962.         parser = FastParser(target)
  963.     else:
  964.         target = Unmarshaller(use_datetime = use_datetime)
  965.         if FastParser:
  966.             parser = FastParser(target)
  967.         elif SgmlopParser:
  968.             parser = SgmlopParser(target)
  969.         elif ExpatParser:
  970.             parser = ExpatParser(target)
  971.         else:
  972.             parser = SlowParser(target)
  973.     return (parser, target)
  974.  
  975.  
  976. def dumps(params, methodname = None, methodresponse = None, encoding = None, allow_none = 0):
  977.     '''data [,options] -> marshalled data
  978.  
  979.     Convert an argument tuple or a Fault instance to an XML-RPC
  980.     request (or response, if the methodresponse option is used).
  981.  
  982.     In addition to the data object, the following options can be given
  983.     as keyword arguments:
  984.  
  985.         methodname: the method name for a methodCall packet
  986.  
  987.         methodresponse: true to create a methodResponse packet.
  988.         If this option is used with a tuple, the tuple must be
  989.         a singleton (i.e. it can contain only one element).
  990.  
  991.         encoding: the packet encoding (default is UTF-8)
  992.  
  993.     All 8-bit strings in the data structure are assumed to use the
  994.     packet encoding.  Unicode strings are automatically converted,
  995.     where necessary.
  996.     '''
  997.     if not isinstance(params, TupleType) and isinstance(params, Fault):
  998.         raise AssertionError, 'argument must be tuple or Fault instance'
  999.     if isinstance(params, Fault):
  1000.         methodresponse = 1
  1001.     elif methodresponse and isinstance(params, TupleType):
  1002.         if not len(params) == 1:
  1003.             raise AssertionError, 'response tuple must be a singleton'
  1004.     
  1005.     if not encoding:
  1006.         encoding = 'utf-8'
  1007.     
  1008.     if FastMarshaller:
  1009.         m = FastMarshaller(encoding)
  1010.     else:
  1011.         m = Marshaller(encoding, allow_none)
  1012.     data = m.dumps(params)
  1013.     if encoding != 'utf-8':
  1014.         xmlheader = "<?xml version='1.0' encoding='%s'?>\n" % str(encoding)
  1015.     else:
  1016.         xmlheader = "<?xml version='1.0'?>\n"
  1017.     if methodname:
  1018.         if not isinstance(methodname, StringType):
  1019.             methodname = methodname.encode(encoding)
  1020.         
  1021.         data = (xmlheader, '<methodCall>\n<methodName>', methodname, '</methodName>\n', data, '</methodCall>\n')
  1022.     elif methodresponse:
  1023.         data = (xmlheader, '<methodResponse>\n', data, '</methodResponse>\n')
  1024.     else:
  1025.         return data
  1026.     return methodname.join(data, '')
  1027.  
  1028.  
  1029. def loads(data, use_datetime = 0):
  1030.     '''data -> unmarshalled data, method name
  1031.  
  1032.     Convert an XML-RPC packet to unmarshalled data plus a method
  1033.     name (None if not present).
  1034.  
  1035.     If the XML-RPC packet represents a fault condition, this function
  1036.     raises a Fault exception.
  1037.     '''
  1038.     (p, u) = getparser(use_datetime = use_datetime)
  1039.     p.feed(data)
  1040.     p.close()
  1041.     return (u.close(), u.getmethodname())
  1042.  
  1043.  
  1044. class _Method:
  1045.     
  1046.     def __init__(self, send, name):
  1047.         self._Method__send = send
  1048.         self._Method__name = name
  1049.  
  1050.     
  1051.     def __getattr__(self, name):
  1052.         return _Method(self._Method__send, '%s.%s' % (self._Method__name, name))
  1053.  
  1054.     
  1055.     def __call__(self, *args):
  1056.         return self._Method__send(self._Method__name, args)
  1057.  
  1058.  
  1059.  
  1060. class Transport:
  1061.     '''Handles an HTTP transaction to an XML-RPC server.'''
  1062.     user_agent = 'xmlrpclib.py/%s (by www.pythonware.com)' % __version__
  1063.     
  1064.     def __init__(self, use_datetime = 0):
  1065.         self._use_datetime = use_datetime
  1066.  
  1067.     
  1068.     def request(self, host, handler, request_body, verbose = 0):
  1069.         h = self.make_connection(host)
  1070.         if verbose:
  1071.             h.set_debuglevel(1)
  1072.         
  1073.         self.send_request(h, handler, request_body)
  1074.         self.send_host(h, host)
  1075.         self.send_user_agent(h)
  1076.         self.send_content(h, request_body)
  1077.         (errcode, errmsg, headers) = h.getreply()
  1078.         if errcode != 200:
  1079.             raise ProtocolError(host + handler, errcode, errmsg, headers)
  1080.         errcode != 200
  1081.         self.verbose = verbose
  1082.         
  1083.         try:
  1084.             sock = h._conn.sock
  1085.         except AttributeError:
  1086.             sock = None
  1087.  
  1088.         return self._parse_response(h.getfile(), sock)
  1089.  
  1090.     
  1091.     def getparser(self):
  1092.         return getparser(use_datetime = self._use_datetime)
  1093.  
  1094.     
  1095.     def get_host_info(self, host):
  1096.         x509 = { }
  1097.         if isinstance(host, TupleType):
  1098.             (host, x509) = host
  1099.         
  1100.         import urllib as urllib
  1101.         (auth, host) = urllib.splituser(host)
  1102.         if auth:
  1103.             import base64
  1104.             auth = base64.encodestring(urllib.unquote(auth))
  1105.             auth = string.join(string.split(auth), '')
  1106.             extra_headers = [
  1107.                 ('Authorization', 'Basic ' + auth)]
  1108.         else:
  1109.             extra_headers = None
  1110.         return (host, extra_headers, x509)
  1111.  
  1112.     
  1113.     def make_connection(self, host):
  1114.         import httplib as httplib
  1115.         (host, extra_headers, x509) = self.get_host_info(host)
  1116.         return httplib.HTTP(host)
  1117.  
  1118.     
  1119.     def send_request(self, connection, handler, request_body):
  1120.         connection.putrequest('POST', handler)
  1121.  
  1122.     
  1123.     def send_host(self, connection, host):
  1124.         (host, extra_headers, x509) = self.get_host_info(host)
  1125.         connection.putheader('Host', host)
  1126.         if extra_headers:
  1127.             if isinstance(extra_headers, DictType):
  1128.                 extra_headers = extra_headers.items()
  1129.             
  1130.             for key, value in extra_headers:
  1131.                 connection.putheader(key, value)
  1132.             
  1133.         
  1134.  
  1135.     
  1136.     def send_user_agent(self, connection):
  1137.         connection.putheader('User-Agent', self.user_agent)
  1138.  
  1139.     
  1140.     def send_content(self, connection, request_body):
  1141.         connection.putheader('Content-Type', 'text/xml')
  1142.         connection.putheader('Content-Length', str(len(request_body)))
  1143.         connection.endheaders()
  1144.         if request_body:
  1145.             connection.send(request_body)
  1146.         
  1147.  
  1148.     
  1149.     def parse_response(self, file):
  1150.         return self._parse_response(file, None)
  1151.  
  1152.     
  1153.     def _parse_response(self, file, sock):
  1154.         (p, u) = self.getparser()
  1155.         while sock:
  1156.             response = sock.recv(1024)
  1157.         response = file.read(1024)
  1158.         if not response:
  1159.             break
  1160.         
  1161.         if self.verbose:
  1162.             print 'body:', repr(response)
  1163.         
  1164.         p.feed(response)
  1165.         continue
  1166.         file.close()
  1167.         p.close()
  1168.         return u.close()
  1169.  
  1170.  
  1171.  
  1172. class SafeTransport(Transport):
  1173.     '''Handles an HTTPS transaction to an XML-RPC server.'''
  1174.     
  1175.     def make_connection(self, host):
  1176.         import httplib
  1177.         (host, extra_headers, x509) = self.get_host_info(host)
  1178.         
  1179.         try:
  1180.             HTTPS = httplib.HTTPS
  1181.         except AttributeError:
  1182.             raise NotImplementedError("your version of httplib doesn't support HTTPS")
  1183.  
  1184.         if not x509:
  1185.             pass
  1186.         return HTTPS(host, None, **{ })
  1187.  
  1188.  
  1189.  
  1190. class ServerProxy:
  1191.     '''uri [,options] -> a logical connection to an XML-RPC server
  1192.  
  1193.     uri is the connection point on the server, given as
  1194.     scheme://host/target.
  1195.  
  1196.     The standard implementation always supports the "http" scheme.  If
  1197.     SSL socket support is available (Python 2.0), it also supports
  1198.     "https".
  1199.  
  1200.     If the target part and the slash preceding it are both omitted,
  1201.     "/RPC2" is assumed.
  1202.  
  1203.     The following options can be given as keyword arguments:
  1204.  
  1205.         transport: a transport factory
  1206.         encoding: the request encoding (default is UTF-8)
  1207.  
  1208.     All 8-bit strings passed to the server proxy are assumed to use
  1209.     the given encoding.
  1210.     '''
  1211.     
  1212.     def __init__(self, uri, transport = None, encoding = None, verbose = 0, allow_none = 0, use_datetime = 0):
  1213.         import urllib
  1214.         (type, uri) = urllib.splittype(uri)
  1215.         if type not in ('http', 'https'):
  1216.             raise IOError, 'unsupported XML-RPC protocol'
  1217.         type not in ('http', 'https')
  1218.         (self._ServerProxy__host, self._ServerProxy__handler) = urllib.splithost(uri)
  1219.         if not self._ServerProxy__handler:
  1220.             self._ServerProxy__handler = '/RPC2'
  1221.         
  1222.         if transport is None:
  1223.             if type == 'https':
  1224.                 transport = SafeTransport(use_datetime = use_datetime)
  1225.             else:
  1226.                 transport = Transport(use_datetime = use_datetime)
  1227.         
  1228.         self._ServerProxy__transport = transport
  1229.         self._ServerProxy__encoding = encoding
  1230.         self._ServerProxy__verbose = verbose
  1231.         self._ServerProxy__allow_none = allow_none
  1232.  
  1233.     
  1234.     def __request(self, methodname, params):
  1235.         request = dumps(params, methodname, encoding = self._ServerProxy__encoding, allow_none = self._ServerProxy__allow_none)
  1236.         response = self._ServerProxy__transport.request(self._ServerProxy__host, self._ServerProxy__handler, request, verbose = self._ServerProxy__verbose)
  1237.         if len(response) == 1:
  1238.             response = response[0]
  1239.         
  1240.         return response
  1241.  
  1242.     
  1243.     def __repr__(self):
  1244.         return '<ServerProxy for %s%s>' % (self._ServerProxy__host, self._ServerProxy__handler)
  1245.  
  1246.     __str__ = __repr__
  1247.     
  1248.     def __getattr__(self, name):
  1249.         return _Method(self._ServerProxy__request, name)
  1250.  
  1251.  
  1252. Server = ServerProxy
  1253. if __name__ == '__main__':
  1254.     server = ServerProxy('http://time.xmlrpc.com/RPC2')
  1255.     print server
  1256.     
  1257.     try:
  1258.         print server.currentTime.getCurrentTime()
  1259.     except Error:
  1260.         v = None
  1261.         print 'ERROR', v
  1262.  
  1263.     multi = MultiCall(server)
  1264.     multi.currentTime.getCurrentTime()
  1265.     multi.currentTime.getCurrentTime()
  1266.     
  1267.     try:
  1268.         for response in multi():
  1269.             print response
  1270.     except Error:
  1271.         v = None
  1272.         print 'ERROR', v
  1273.     except:
  1274.         None<EXCEPTION MATCH>Error
  1275.     
  1276.  
  1277. None<EXCEPTION MATCH>Error
  1278.